package com.easychat.websocket.netty;

import com.easychat.dto.TokenUserInfoDto;
import com.easychat.redis.RedisComponent;
import com.easychat.websocket.ChannelContextUtils;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.util.Attribute;
import io.netty.util.AttributeKey;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * 自定义的webSocket处理
 * @author 10 2024/10/18
 */
@Slf4j
@Component
@ChannelHandler.Sharable
public class HandlerWebSocket extends SimpleChannelInboundHandler<TextWebSocketFrame> {
     @Resource
     private RedisComponent redisComponent;

     @Resource
     private ChannelContextUtils channelContextUtils;

     /**
      * 通道就绪后调用
      * @param ctx
      * @throws Exception
      */
     @Override
     public void channelActive(ChannelHandlerContext ctx) throws Exception {
          log.info("有新的连接加入....");
     }

     @Override
     public void channelInactive(ChannelHandlerContext ctx) throws Exception {
          log.info("有连接断开");
          channelContextUtils.removeContext(ctx.channel());
     }

     /**
      * 接收消息
      * @param ctx
      * @param textWebSocketFrame
      * @throws Exception
      */
     @Override
     protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame textWebSocketFrame) throws Exception {
          Channel channel = ctx.channel();
          Attribute<String> attribute = channel.attr(AttributeKey.valueOf(channel.id().toString()));
          String userId = attribute.get();
          log.info("收到userId：{}的消息：{}",userId,textWebSocketFrame.text());
          //消息过来，保存心跳
          redisComponent.saveUserHeartBeat(userId);
     }

     /**
      * 在read之前执行
      * 根据url获取token ，获取userId
      * @param ctx
      * @param evt
      * @throws Exception
      */
     @Override
     public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
          if(evt instanceof WebSocketServerProtocolHandler.HandshakeComplete){
               WebSocketServerProtocolHandler.HandshakeComplete complete = (WebSocketServerProtocolHandler.HandshakeComplete) evt;
               String url = complete.requestUri();
               String token = getToken(url);
               if(token == null){
                    ctx.channel().close();
                    return;
               }
               TokenUserInfoDto tokenUserInfoDto = redisComponent.getTokenUserInfoDto(token);
               if(null == tokenUserInfoDto){
                    ctx.channel().close();
                    return;
               }
               channelContextUtils.addContext(tokenUserInfoDto.getUserId(), ctx.channel());
               log.info("url:{}",url);
          }
          super.userEventTriggered(ctx, evt);
     }
     public String getToken(String url){
          if(url == null){
               return null;
          }
          String[] queryParams = url.split("\\?");
          if(queryParams.length != 2){
               return null;
          }
          String[] params = queryParams[1].split("=");
          if(params.length != 2){
               return null;
          }
          return params[1];
     }

}
